package com.xiaoowuu.wherecanigo

import android.graphics.Color
import android.location.Location
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.*
import com.amap.api.services.busline.*
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.core.PoiItem
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import com.amap.api.services.poisearch.PoiResult
import com.amap.api.services.poisearch.PoiSearch
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity(),
        PoiSearch.OnPoiSearchListener,
        GeocodeSearch.OnGeocodeSearchListener,
        AMap.OnMyLocationChangeListener,
        BusLineSearch.OnBusLineSearchListener,
        BusStationSearch.OnBusStationSearchListener,
        AMap.OnMarkerClickListener,
        BusStationAdapter.ShowBusLineListener,
        BusLineAdapter.ShowBusLineDetailListener, SettingDialog.OnSettingChangedListener {
    companion object {
        const val LEVEL_NEARBY_AREA = 0f
        const val LEVEL_MY_LOCATION = 1f
        const val LEVEL_BUS_LINE = 2f
        const val LEVEL_STATION = 3f
    }

    var location: Location? = null
    var cityCode = ""
    var busStations: List<PoiItem> = emptyList()
    var busStationMarkers: List<Marker> = emptyList()
    var currentBusStationItem: BusStationItem? = null
    var stationCount = 0
    var nearbyRadius = 0
    val busStationAdapter: BusStationAdapter by lazy {
        val adapter = BusStationAdapter()
        adapter.showBusLineListener = this
        adapter
    }

    private var drawnBusLine: Polyline? = null
    private var drawnStations: ArrayList<Marker>? = null
    private var drawnEndStation: Marker? = null

    private var busLineDialog: BusLineDialog? = null

    override fun onMyLocationChange(p0: Location?) {
        p0?.let {
            ivSetting.performClick()
            location = it
            map.map.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(it.latitude, it.longitude), 16f))
        }
    }

    override fun onRegeocodeSearched(p0: RegeocodeResult?, p1: Int) {
        p0?.let {
            searchNearbyBusStation(it.regeocodeAddress.cityCode)
        }
    }

    override fun onGeocodeSearched(p0: GeocodeResult?, p1: Int) {
    }

    override fun onPoiItemSearched(p0: PoiItem?, p1: Int) {
    }

    override fun onPoiSearched(p0: PoiResult?, p1: Int) {
        p0?.let {
            busStations = it.pois
            busStationAdapter.data = busStations
            busStationMarkers = map.map.addMarkers(
                    busStations.map { station ->
                        MarkerOptions()
                                .zIndex(LEVEL_STATION)
                                .position(LatLng(station.latLonPoint.latitude, station.latLonPoint.longitude))
                                .icon(BitmapDescriptorFactory.fromView(PointView(this, 36, Color.WHITE, 12, Color.parseColor("#4CAF50"))))
                                .anchor(0.5f, 0.5f)
                    } as ArrayList<MarkerOptions>,
                    false)
        }
    }

    override fun onBusStationSearched(p0: BusStationResult?, p1: Int) {
        flLoading.visibility = View.GONE
        p0?.let {
            if (!it.busStations.isEmpty()) {
                currentBusStationItem = it.busStations[0]
                val dialog = BusLineDialog.newInstance(it.busStations[0].busLineItems)
                dialog.adapter.showBusLineDetailListener = this
                dialog.show(supportFragmentManager, null)
                busLineDialog = dialog
            }
        }
    }

    override fun onBusLineSearched(p0: BusLineResult?, p1: Int) {
        flLoading.visibility = View.GONE
        p0?.apply {
            if (!busLines.isEmpty()) {
                val busLine = busLines[0]
                val busStations = busLine.busStations
                val currentStationIndex = busStations.indexOf(currentBusStationItem)
                if (currentStationIndex == busStations.size - 1) {
                    return
                }
                if (currentStationIndex > -1) {
                    val startIndex = currentStationIndex
                    val endIndex = if (currentStationIndex + stationCount < busStations.size) {
                        currentStationIndex + stationCount
                    } else {
                        busStations.size - 1
                    }
                    val startPoint = busStations[startIndex].latLonPoint
                    val endPoint = busStations[endIndex].latLonPoint
                    val startPointIndex = busLine.directionsCoordinates.indexOf(startPoint)
                    val endPointIndex = busLine.directionsCoordinates.indexOf(endPoint)

                    drawnBusLine?.remove()
                    drawnStations?.forEach { item -> item.remove() }
                    drawnEndStation?.remove()

                    //绘制公交路线
                    drawnBusLine = map.map.addPolyline(PolylineOptions()
                            .zIndex(LEVEL_BUS_LINE)
                            .addAll(busLine.directionsCoordinates.subList(startPointIndex, endPointIndex + 1).map { point -> LatLng(point.latitude, point.longitude) })
                            .color(Color.parseColor("#0091ea"))
                            .width(12f))
                    //终点
                    drawnEndStation = map.map.addMarker(MarkerOptions()
                            .zIndex(LEVEL_STATION)
                            .position(LatLng(busStations[endIndex].latLonPoint.latitude, busStations[endIndex].latLonPoint.longitude))
                            .icon(BitmapDescriptorFactory.fromView(PointView(this@MainActivity, 36, Color.WHITE, 12, Color.parseColor("#E91E63"))))
                            .anchor(0.5f, 0.5f))
                    //沿途站点
                    drawnStations = map.map.addMarkers(busStations.subList(startIndex + 1, endIndex)
                            .map { station ->
                                MarkerOptions()
                                        .zIndex(LEVEL_STATION)
                                        .position(LatLng(station.latLonPoint.latitude, station.latLonPoint.longitude))
                                        .icon(BitmapDescriptorFactory.fromView(PointView(this@MainActivity, 24, Color.WHITE, 2, Color.BLACK)))
                                        .anchor(0.5f, 0.5f)
                            } as ArrayList<MarkerOptions>,
                            true)
                }
            }
        }
    }

    /**
     * 绘制定位位置
     */
    private fun drawMyLocation() {
        map.map.clear()
        map.map.addCircle(CircleOptions()
                .zIndex(LEVEL_NEARBY_AREA)
                .center(LatLng(location!!.latitude, location!!.longitude))
                .radius(nearbyRadius.toDouble())
                .fillColor(Color.parseColor("#20f42d55"))
                .strokeWidth(0f))
        map.map.addMarker(MarkerOptions()
                .zIndex(LEVEL_MY_LOCATION)
                .icon(BitmapDescriptorFactory.fromView(PointView(this, 54, Color.WHITE, 18, Color.parseColor("#f42d55"))))
                .position(LatLng(location!!.latitude, location!!.longitude))
                .anchor(0.5f, 0.5f))
    }

    override fun onMarkerClick(p0: Marker?): Boolean {
        val index = busStationMarkers.indexOf(p0)
        if (index > -1) {
            p0?.zIndex = LEVEL_STATION
            dsvBusStations.scrollToPosition(index)
            focusStation(busStations[index])
            return true
        }
        return false
    }

    override fun showBusLine(station: PoiItem) {
        flLoading.visibility = View.VISIBLE
        val busStationSearch = BusStationSearch(this, BusStationQuery(station.title, cityCode))
        busStationSearch.setOnBusStationSearchListener(this)
        busStationSearch.searchBusStationAsyn()
    }

    override fun showBusLineDetail(line: BusLineItem) {
        busLineDialog?.dismiss()
        flLoading.visibility = View.VISIBLE
        val busLineSearch = BusLineSearch(this, BusLineQuery(line.busLineId, BusLineQuery.SearchType.BY_LINE_ID, cityCode))
        busLineSearch.setOnBusLineSearchListener(this)
        busLineSearch.searchBusLineAsyn()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //在activity执行onCreate时执行map.onCreate(savedInstanceState)，创建地图
        map.onCreate(savedInstanceState)

        dsvBusStations.adapter = this.busStationAdapter
        dsvBusStations.setItemTransitionTimeMillis(200)
        dsvBusStations.addOnItemChangedListener { viewHolder, adapterPosition ->
            if (adapterPosition > -1 && adapterPosition < busStations.size) {
                focusStation(busStations[adapterPosition])
            }
        }

        map.map.setOnMarkerClickListener(this)
        map.map.setOnMyLocationChangeListener(this)
        map.map.uiSettings.isRotateGesturesEnabled = false
        map.map.uiSettings.isZoomControlsEnabled = false
        map.map.uiSettings.isCompassEnabled = false
        val locationStyle = MyLocationStyle()
        locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE)
        locationStyle.showMyLocation(true)
        locationStyle.showMyLocation(false)
        map.map.myLocationStyle = locationStyle
        map.map.isMyLocationEnabled = true

        ivSetting.setOnClickListener {
            val dialog = SettingDialog.newInstance(nearbyRadius, stationCount)
            dialog.isCancelable = location != null
            dialog.onSettingChangedListener = this
            dialog.show(supportFragmentManager, null)
        }
        ivLocate.setOnClickListener {

        }
    }

    private fun focusStation(station: PoiItem) {
        val point = LatLng(station.latLonPoint.latitude, station.latLonPoint.longitude)
        map.map.animateCamera(CameraUpdateFactory.newLatLngZoom(point, 17f))
    }

    private fun getCityInfo(location: Location) {
        val geocodeSearch = GeocodeSearch(this)
        geocodeSearch.setOnGeocodeSearchListener(this)
        geocodeSearch.getFromLocationAsyn(RegeocodeQuery(LatLonPoint(location.latitude, location.longitude), 0f, GeocodeSearch.AMAP))
    }

    private fun searchNearbyBusStation(cityCode: String) {
        this.cityCode = cityCode
        location?.let {
            //关键字,点类别,城市编码
            //150702公交站 150500地铁站
            val query = PoiSearch.Query("", "150700|150500", cityCode)
            // 设置每页最多返回多少条poiitem
            query.pageSize = 30
            //设置查询页码
            query.pageNum = 0
            query.isDistanceSort = true
            val poiSearch = PoiSearch(this, query)
            //搜索定位点附近1000米公交站、地铁站
            poiSearch.bound = PoiSearch.SearchBound(LatLonPoint(it.latitude, it.longitude), nearbyRadius)
            poiSearch.setOnPoiSearchListener(this)
            poiSearch.searchPOIAsyn()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        //在activity执行onDestroy时执行map.onDestroy()，销毁地图
        map.onDestroy()
    }

    override fun onResume() {
        super.onResume()
        //在activity执行onResume时执行map.onResume ()，重新绘制加载地图
        map.onResume()
    }

    override fun onPause() {
        super.onPause()
        //在activity执行onPause时执行map.onPause ()，暂停地图的绘制
        map.onPause()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        //在activity执行onSaveInstanceState时执行map.onSaveInstanceState (outState)，保存地图当前的状态
        map.onSaveInstanceState(outState)
    }

    override fun onSettingChanged(distance: Int, stationCount: Int) {
        busStationAdapter.data = emptyList()
        this.nearbyRadius = distance
        this.stationCount = stationCount
        location?.let {
            drawMyLocation()
            getCityInfo(it)
        }
    }

}
